package jal4eclipse.builder;

import jal4eclipse.jal.JALCompileResult;
import jal4eclipse.jal.JALErrors;
import jal4eclipse.jal.JALParser;
import jal4eclipse.jal.JALV2Compiler;
import jal4eclipse.ui.console.JALConsole;
import jal4eclipse.ui.editors.FileUtil;
import jal4eclipse.ui.prefpages.Page1;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;

class CompileResourceVisitor implements IResourceVisitor {
	private List results = new ArrayList();
	public boolean visit(IResource resource) {
		JALCompileResult result = JALBuilder.compile(resource);
		if (result != null) {
			results.add(result);
		}
		//return true to continue visiting children.
		return true;
	}

	

	public List getResults() {
		return results;
	}

	public void setResults(List results) {
		this.results = results;
	}
}



public class JALBuilder extends IncrementalProjectBuilder{
	public static final String BUILDER_ID = "JAL4Eclipse.JALBuilder";
	
	
	protected IProject[] build(int arg0, Map arg1, IProgressMonitor arg2)
			throws CoreException {
			
			CompileResourceVisitor visitor = new CompileResourceVisitor();
			getProject().accept(visitor);
			
			List results = visitor.getResults();
			for (Iterator it = results.iterator();it.hasNext();) {
				JALCompileResult result = (JALCompileResult) it.next();	
				// Display compilation result to console
				JALConsole.write(result.getCommandLine());
				JALConsole.write(result.getResult());
				getCommand().getBuilderName();
			}
			
			try {
				ResourcesPlugin.getWorkspace().getRoot().refreshLocal(
						IResource.DEPTH_INFINITE, null);
			} catch (CoreException e) {
				e.printStackTrace();
			}
			
		return  new IProject[0]; 
	}

	protected void clean(IProgressMonitor arg0) throws CoreException {
		//System.out.println("Clean");
	}

	protected void startupOnInitialize() {
		//System.out.println("Startup ");
		
	}
	
	public static JALCompileResult compile(IResource resource) {
		if ("jal".equals(resource.getFileExtension())) {
			if (JALParser.isMainFile(resource.getLocation().toOSString())) {
				JALCompileResult result = compileResource(resource);
				updateMarkers(resource,result);
				return result;
			}
		}
		return null;
	}
	
	/*
	 * 
	 */
	public static  JALCompileResult compileResource(IResource resource) {
		StringBuffer libPath = new StringBuffer(); 
		List prjList = new ArrayList();
		IProject prj = resource.getProject();
		prjList.add(prj);
		try {
			IProject[] refPrj = prj.getReferencedProjects();
			for (int i = 0;i<refPrj.length;i++) {
				prjList.add(refPrj[i]);
			}
		} catch (CoreException e) {
			JALConsole.write(e);
		}

		
		for (Iterator it = prjList.iterator();it.hasNext();) {
			IProject p = (IProject) it.next();
			List prjSubDirs;
			try {
				prjSubDirs = FileUtil.getFileListing(new File(p.getLocation().toOSString()));
				libPath.append(";"+p.getLocation().toOSString());
				for (Iterator subIt = prjSubDirs.iterator();subIt.hasNext();) {
					File file = (File)subIt.next();
					
					// exclude some dirs like '.settings'
					if ((file.isDirectory())&&(!file.getName().startsWith("."))) {
						String path = file.getAbsolutePath();
						libPath.append(";"+path);
					}
					
				}
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}
		
		String libPathStr=libPath.toString();
		if (libPathStr.startsWith(";")) {
			libPathStr = libPathStr.substring(1);
		}
		
		String options = Page1.getCompilerOptions();
		String COMPILER_PATH = Page1.getCompilerPath();
		String mainFile = resource.getLocation().toOSString();
		JALCompileResult result = JALV2Compiler.compile(COMPILER_PATH, mainFile,
				libPathStr, options);
		return result;
	}
	
	/*
	 * Update markers to show errors and warnings
	 */
	public static void updateMarkers(IResource resource,JALCompileResult result) {
		/*
		 * Update Markers
		 */
		IMarker marker;
		try {
			// Delete Markers on all needed files
			IFile[] files = FileUtil.findAllReferencedFiles(resource.getProject());
			for (int i = 0; i < files.length; i++) {
				// Clear existing error markup
				IFile file = files[i];
				if (file != null) {
					int depth = IResource.DEPTH_INFINITE;
					try {
						file.deleteMarkers(IMarker.PROBLEM, true, depth);
					} catch (CoreException e) {
						JALConsole.write(e.getMessage());
					}
				}
			}

			// Add new Markers
			for (int i = 0; i < result.getErrors().length; i++) {
				JALErrors err = result.getErrors()[i];
				IFile file = FileUtil.toIFile(resource.getProject(), err
						.getFile());
				if (file != null) {
					marker = file.createMarker(IMarker.PROBLEM);
					int line = err.getLine(); // 1 based
					if (marker.exists()) {
						marker.setAttribute(IMarker.MESSAGE, err.getMessage());
						if (err.getMessage().startsWith(" warning: ")) {
							marker.setAttribute(IMarker.SEVERITY, new Integer(
									IMarker.SEVERITY_WARNING));
						} else {
							marker.setAttribute(IMarker.SEVERITY, new Integer(
									IMarker.SEVERITY_ERROR));
						}
						marker.setAttribute(IMarker.PRIORITY,
								IMarker.PRIORITY_HIGH);
//						marker.setAttribute(IMarker.CHAR_START, pos[0]);
//						marker.setAttribute(IMarker.CHAR_END, pos[1]);
						marker.setAttribute(IMarker.LINE_NUMBER, line);
						marker.setAttribute(IMarker.LOCATION, "Line " + line);
					}
				}
			}
		} catch (Exception e) {
			JALConsole.write(e);
		}
	}
	
	
	
}
